package cn.parllay.dingdangproject.service;

import java.util.concurrent.TimeUnit;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import cn.parllay.dingdangproject.entity.Constants;
import cn.parllay.dingdangproject.entity.ReplyMsg;
import cn.parllay.dingdangproject.entity.ReplyServerBody;
import cn.parllay.dingdangproject.service.handler.NettyServerHandler;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.serialization.ClassResolvers;
import io.netty.handler.codec.serialization.ObjectDecoder;
import io.netty.handler.codec.serialization.ObjectEncoder;
import io.netty.handler.timeout.IdleStateHandler;

public class NettyServerBootstrap {

	private int port=9999;

	@SuppressWarnings("unused")
	private SocketChannel socketChannel;
    
    private ServerBootstrap bootstrap;
    
    public NettyServerBootstrap() throws InterruptedException {
        bind();
    }
    
    public NettyServerBootstrap(int port) throws InterruptedException {
        this.port = port;
        bind();
    }
 
    private void bind() {
        EventLoopGroup boss=new NioEventLoopGroup();
        EventLoopGroup worker=new NioEventLoopGroup();
        bootstrap=new ServerBootstrap();
        bootstrap.group(boss,worker);
        bootstrap.channel(NioServerSocketChannel.class);
        //用来初始化服务端可连接队列的大小 
        bootstrap.option(ChannelOption.SO_BACKLOG, 65535);
        //通过NoDelay禁用Nagle,使消息立即发出去，不用等待到一定的数据量才发出去
        bootstrap.option(ChannelOption.TCP_NODELAY, true);
        //保持长连接状态
        bootstrap.childOption(ChannelOption.SO_KEEPALIVE, true);
        bootstrap.childHandler(new ChannelInitializer<SocketChannel>() {
            @Override
            protected void initChannel(SocketChannel socketChannel) throws Exception {
                ChannelPipeline p = socketChannel.pipeline();
                //心跳包     第一个参数 85 表示读操作空闲时间(心跳超时时间)      第二个参数 50 表示写操作空闲时间    第三个参数 100 表示读写操作空闲时间      第四个参数 单位
            	p.addLast(new IdleStateHandler(130, 70, 150, TimeUnit.SECONDS));
                p.addLast(new ObjectEncoder());
                p.addLast(new ObjectDecoder(ClassResolvers.cacheDisabled(null)));
                p.addLast(new NettyServerHandler());
            }
        });
		try {
			ChannelFuture f = bootstrap.bind(port).sync();
			if(f.isSuccess()){
	            System.out.println("server start---------------");
	        }
		} catch (InterruptedException e) {
			e.printStackTrace();
			boss.shutdownGracefully();  
			worker.shutdownGracefully();
		}
        
    }
    
    //启动加载这个类 也可以达到spring启动加载netty的目的
    @SuppressWarnings({ "unused", "resource" })
	private NettyServerHandler getNettyServerHandler() {
    	ApplicationContext context=new ClassPathXmlApplicationContext("classpath*:META-INF/applicationContext.xml");
    	return (NettyServerHandler)context.getBean("nettyServerHandler");
    }
    
    
    @SuppressWarnings("unused")
	public static void main(String []args) throws InterruptedException {
        NettyServerBootstrap bootstrap=new NettyServerBootstrap(9999);
        Constants.setClientId("robin");
        while (true){
            SocketChannel channel=(SocketChannel)NettyChannelMap.get("robin");
            if(channel!=null){
                /*ReplyClientBody replyClientBody=new ReplyClientBody("server reply ----");
                ReplyMsg replyMsg=new ReplyMsg();
                replyMsg.setBody(replyClientBody);
                channel.writeAndFlush(replyMsg);*/
            	
            	ReplyServerBody replyBody=new ReplyServerBody("server info--收到了22");
                ReplyMsg replyMsg=new ReplyMsg();
                replyMsg.setBody(replyBody);
                NettyChannelMap.get(Constants.getClientId()).writeAndFlush(replyMsg);
            	
	            channel.writeAndFlush(replyMsg);
            }
            TimeUnit.SECONDS.sleep(5);
        }
    }
}
